package com.ease.core.managers {
   import com.ease.core.components.DockingView;
   import com.ease.core.model.ViewDefine;
   import com.ease.util.IconUtil;
   import com.ease.util.MruCache;
   import com.ease.util.ReflectionUtil;
   
   import flash.events.Event;
   import flash.events.EventDispatcher;
   import flash.utils.Dictionary;
   
   import mx.core.UIComponent;
   
   public class ViewManager extends EventDispatcher {
      private var _viewDefineCache:MruCache = new MruCache(400);
      private var _viewInstanceCache:MruCache = new MruCache(400);
      
      private static var _instance:ViewManager = null;
      public static function getInstance():ViewManager {
         if (!_instance) {
            _instance = new ViewManager();
         }
         return _instance;
      }
      
      public function ViewManager() {
         if (_instance) {
            throw new Error('ViewManager is singleton');
         }
      }
      
      public function addViewDefine(viewId:String, view:ViewDefine):void {
         _viewDefineCache.add(viewId, view);
      }
      
      public function createViewInstance(id:String, perspective:String, createNew:Boolean = false):DockingView {
         var view:DockingView = null;
         if (createNew) {
            view = createViewInner(id);
            addViewInstance(id, perspective, view);
         }
         else {
            var views:Array = getViewInstance(id, perspective);
            if (views && views.length > 0) {
               view = views[0];
            }
            if (!view) {
               view = createViewInner(id);
               addViewInstance(id, perspective, view);
            }
         }
         view.perspectiveId = perspective;
         return view;
      }
      
      private function createViewInner(id:String):DockingView {
         var viewDef:ViewDefine = _viewDefineCache.getValue(id) as ViewDefine;
         var view:DockingView
         try {
            view =
               ReflectionUtil.newInstance(viewDef.type, null) as DockingView;
         } 
         catch(error:Error) {
            trace(error.message);
         }
         if (!view) {
            view = new DockingView();
         }
         view.viewId = id;
         view.label = viewDef.label;
         view.icon = IconUtil.getClass(view, viewDef.icon, 16, 16);
         view.location = viewDef.location;
         view.index = viewDef.index;
         return view;
      }
      
      private function addViewInstance(id:String, perspective:String, value:DockingView):void {
         var map:MruCache = _viewInstanceCache.getValue(id);
         if (!map) {
            map = new MruCache(15);
            _viewInstanceCache.add(id, map);
         }
         var viewList:Array = map.getValue(perspective);
         if (!viewList) {
            viewList = [];
            map.add(perspective, viewList);
         }
         if (viewList.indexOf(value) == -1) {
            viewList.push(value);
         }
      }
      
      public function removeViewInstanceById(id:String, perspective:String):void {
         var map:MruCache = _viewInstanceCache.getValue(id);
         if (map) {
            if (perspective != null) {
               map.remove(perspective);
            }
            else {
               _viewInstanceCache.remove(id);
            }
         }
      }
      
      public function removeViewInstance(view:DockingView, perspective:String):void {
         var cachedViews:Array = getViewInstance(view.viewId, perspective);
         if (cachedViews && cachedViews.length > 0 && cachedViews.indexOf(view) != -1) {
            cachedViews.splice(cachedViews.indexOf(view), 1);
         }
      }
      
      public function removeAllViewInstance():void {
         _viewInstanceCache.removeAll();
      }
      
      public function getViewInstance(id:String, perspective:String):Array {
         var map:MruCache = _viewInstanceCache.getValue(id);
         return map ? map.getValue(perspective) : null;
      }
      
      private var _activeViewWindow:String;

      [Bindable("activeViewWindowChange")]
      public function get activeViewWindow():String {
         return _activeViewWindow;
      }

      public function set activeViewWindow(value:String):void {
         if (_activeViewWindow != value) {
            _activeViewWindow = value;
            dispatchEvent(new Event("activeViewWindowChange"));
         }
      }

      
      public function get viewIds():Array {
         return _viewDefineCache.keys;
      }
      
      public function get viewDefines():Array {
         return _viewDefineCache.values;
      }
      
      public function getViewDefine(id:String):ViewDefine {
         var viewDefine:ViewDefine = _viewDefineCache.getValue(id)
         return _viewDefineCache.getValue(id);
      }
      
      public function clear():void {
         removeAllViewInstance();
         _viewDefineCache.removeAll();
      }
   }
}